#include "SecurityCore.h"
#include "SGD Wrappers/CSGD_XAudio2.h"
#include "SGD Wrappers/CSGD_TextureManager.h"
#include "Event.h"
#include "EventSystem.h"
#include "MessageSystem.h"
#include "DestroyEntityMessage.h"
#include "GamePlayState.h"
#include "Tile.h"
#include "CreatePickUpMessage.h"
#include "Game.h"
#include "Player.h"
#include "Room.h"
#include "CutsceneState.h"
#include "Animation.h"

#include "SwarmBot.h"
#include "TankBot.h"
#include "TurretBot.h"

#include "SaviorPart.h"

SecurityCore::SecurityCore() 
{
	type = OBJ_ENEMY;
	SetHealth(300.0f);
	SetSpeed(0);
	SetAttackTimer(0.0f);

	int randParts = rand() % 2 + 1;
	SetMetal(randParts);
	SetCircuitry(randParts);

	hit = 0;
	hide = false;
	hideTimer = 0.0f;

	wave = -1;
	previousHealth = GetHealth();

	DeathSound = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/Boss_Explode.wav"));
	SpawnSound = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/Core_Spawn.wav"));
	HideSound = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/Core_Hide.wav"));

	EventSystem::GetInstance()->RegisterClient("target_hit", this);
}

SecurityCore::~SecurityCore() 
{	
	EventSystem::GetInstance()->UnregisterClientAll(this);
}

void SecurityCore::Update(float elapsed) 
{
	int camx = GamePlayState::GetInstance()->GetCamX();
	int camy = GamePlayState::GetInstance()->GetCamY();
	if( GetX() > camx + 800 || GetX() + GetWidth() < camx || GetY() + GetHeight() < camy || GetY() > camy + 600 )
	{
		return;
	}

	Enemy::Update(elapsed);

	// Check if dead
	if(GetHealth() <= 0)
	{
		// Give the players resources
		/*if( GamePlayState::GetInstance()->GetPlayer2() )
		{
		GamePlayState::GetInstance()->GetPlayer2()->SetMetal(GamePlayState::GetInstance()->GetPlayer2()->GetMetal() + 50);
		GamePlayState::GetInstance()->GetPlayer2()->SetCircuitry(GamePlayState::GetInstance()->GetPlayer2()->GetCircuitry() + 50);
		GamePlayState::GetInstance()->GetPlayer()->SetMetal(GamePlayState::GetInstance()->GetPlayer()->GetMetal() + 50);
		GamePlayState::GetInstance()->GetPlayer()->SetCircuitry(GamePlayState::GetInstance()->GetPlayer()->GetCircuitry() + 50);
		}
		else
		{
		GamePlayState::GetInstance()->GetPlayer()->SetMetal(GamePlayState::GetInstance()->GetPlayer()->GetMetal() + 100);
		GamePlayState::GetInstance()->GetPlayer()->SetCircuitry(GamePlayState::GetInstance()->GetPlayer()->GetCircuitry() + 100);
		}*/

		CSGD_XAudio2::GetInstance()->SFXPlaySound(DeathSound);
		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;

		// Drop a savior part
		SaviorPart* s = new SaviorPart();
		s->SetX(GetX());
		s->SetY(GetY());
		s->SetHeight(32);
		s->SetWidth(32);
		s->SetPart(0);
		ObjectManager::GetInstance()->AddObject(s);

		return;
	}

	if(disabled == true)
		return;

	// Update animation
	for(int i = 0; i < 2; ++i)
		core[i].Update(elapsed);

	// DPS
	if(hideTimer <= 0.0f)
		previousHealth = GetHealth();

	hideTimer += elapsed;

	if(hideTimer >= waitTime)
	{
		if(1-GetHealth()/previousHealth >= 0.5)
		{
			waitTime = 3.0f;
			hide = true;
			if(hide == false)
				CSGD_XAudio2::GetInstance()->SFXPlaySound(HideSound);
			//hit = 3;
		}
		else
		{
			waitTime = 1.0f;
			//hide = false;
			//hit = 0;
		}
		//hideTimer = 0.0f;
	}

	// Hide?
	if(hide == true)
	{
		if(core[1].IsPlaying() == false && core[1].GetCurFrame() != 2)
			core[1].Play();
		hideTimer += elapsed;
		if(hideTimer >= 5.0f)
		{
			CSGD_XAudio2::GetInstance()->SFXPlaySound(HideSound);
			hideTimer = 0.0f;
			hide = false;
		}
		//if(core[1].IsPlaying() == false)
		//core[1].SetCurFrame(2);
	}

	// Attack
	SetAttackTimer(GetAttackTimer()+(1.0f*elapsed));
	if(hide == false && GetX() < GamePlayState::GetInstance()->GetCamX()+Game::GetInstance()->GetScreenWidth() && GetY() < GamePlayState::GetInstance()->GetCamY()+Game::GetInstance()->GetScreenHeight()
		&& GetX() > GamePlayState::GetInstance()->GetCamX() && GetY() > GamePlayState::GetInstance()->GetCamY())
		Attack();
}

void SecurityCore::Render() 
{
	if(GetX() < GamePlayState::GetInstance()->GetCamX()+Game::GetInstance()->GetScreenWidth() && GetY() < GamePlayState::GetInstance()->GetCamY()+Game::GetInstance()->GetScreenHeight()
		&& GetX() > GamePlayState::GetInstance()->GetCamX() && GetY() > GamePlayState::GetInstance()->GetCamY())
	{
		CSGD_Direct3D::GetInstance()->GetSprite()->Flush();
		if(hide == false)
			core[0].Render((int)GetX()- GamePlayState::GetInstance()->GetCamX(),(int)GetY()- GamePlayState::GetInstance()->GetCamY(),1.0f,D3DCOLOR_ARGB(255,255,hide==true ? 0 : 255,hide==true ? 0 : 255),false);
		else
			core[1].Render((int)GetX()- GamePlayState::GetInstance()->GetCamX(),(int)GetY()- GamePlayState::GetInstance()->GetCamY(),1.0f,D3DCOLOR_ARGB(255,255,hide==true ? 0 : 255,hide==true ? 0 : 255),false);
	}
}

void SecurityCore::Attack() 
{
	if(GetAttackTimer() > 10.0f && GetX() < GamePlayState::GetInstance()->GetCamX()+Game::GetInstance()->GetScreenWidth() && GetY() < GamePlayState::GetInstance()->GetCamY()+Game::GetInstance()->GetScreenHeight()
		&& GetX() > GamePlayState::GetInstance()->GetCamX() && GetY() > GamePlayState::GetInstance()->GetCamY())
	{
		SetAttackTimer(0.0f);
		AddEnemies(20);
		CSGD_XAudio2::GetInstance()->SFXPlaySound(SpawnSound);
		core[0].Play();
	}
}

RECT SecurityCore::GetRect()
{
	RECT tmp = core[0].GetCollsionRect();

	int width = tmp.right;
	int height = tmp.bottom;
	tmp.top += (long)(GetY() - core[0].GetAPoint().fY + height);
	tmp.bottom = height + tmp.top;
	tmp.left += (long)(GetX() - core[0].GetAPoint().fX + (width/2));
	tmp.right = width + tmp.left;

	return tmp;
}

void SecurityCore::HandleEvent(Event* thisEvent)
{
	if(thisEvent->GetParameter() != this)
		return;

	if(thisEvent->GetEventID() == "target_hit" && GetHealth() > 0 && hide != true)
	{
		SetHealth(GetHealth() - 20 /**((float*)(thisEvent->GetParameter2()))*/);
	}
}

void SecurityCore::AddEnemies(int diff)
{
	// Selects Enemy
	float spawnTimer = 25.0f;
	int enemyCount = 0;
	Enemy* enemy = nullptr;
	while(diff > 0)
	{
		enemy = nullptr;
		int r = rand()%2+1;
		if(r == 1 && diff >= 5)
		{
			while(spawnTimer > 0)
			{
				spawnTimer -= 0.1f;
			}
			int tmpID[8];
			for(int j = 0; j < 8; ++j)
			{
				Animation* tmpAnimation = new Animation();
				tmpAnimation->LoadAnimationFromFile("SwarmAnimation.xml", j);
				tmpID[j] = AnimationSystem::GetInstance()->AddAnimation(tmpAnimation);
			}
			enemy = new SwarmBot();
			enemy->SetX(GetX());
			enemy->SetY(GetY());
			enemy->SetRoomNum(GetRoomNum());
			dynamic_cast<SwarmBot*>(enemy)->SetAnimation(tmpID);
			if(enemyCount >= 1)
			{
				for(int j = 0; j < enemyCount; ++j)
				{
					if(enemy->GetX() == enemy->GetX())
						enemy->SetX(enemy->GetX()+128);
				}
			}
			spawnTimer = 25.0f;
			enemyCount += 1;
			diff -= 5;
			room[GetRoomNum()-1]->AddEnemy(enemy);
		}
		else if(r == 2 && diff >= 15)
		{
			while(spawnTimer > 0)
			{
				spawnTimer -= 0.1f;
			}
			int tmpID[8];
			for(int j = 0; j < 8; ++j)
			{
				Animation* tmpAnimation = new Animation();
				tmpAnimation->LoadAnimationFromFile("TankAnimation.xml", j);
				tmpID[j] = AnimationSystem::GetInstance()->AddAnimation(tmpAnimation);
			}
			enemy = new TankBot();
			enemy->SetX(GetX());
			enemy->SetY(GetY());
			enemy->SetRoomNum(GetRoomNum());
			dynamic_cast<TankBot*>(enemy)->SetAnimation(tmpID);
			if(enemyCount >= 1)
			{
				for(int j = 0; j < enemyCount; ++j)
				{
					if(enemy->GetX() == enemy->GetX())
						enemy->SetX(enemy->GetX()+128);
				}
			}
			spawnTimer = 25.0f;
			enemyCount += 1;
			diff -= 15;
			room[GetRoomNum()-1]->AddEnemy(enemy);
		}
	}
}

void SecurityCore::SetAnimation(int id[2])
{
	for(int i = 0; i < 2; ++i)
	{
		core[i] = *AnimationSystem::GetInstance()->GetAnimation(id[i]);
	}

	SetWidth(core[0].GetCollsionRect().right);
	SetHeight(core[0].GetCollsionRect().bottom);
}